﻿#include "ssResManager.h"
#include "algorithms/md5.h"
#include "tools/ssProcessInfo.h"
#ifdef SS_USE_WXWIDGETS
#include "../texture/ssWXPicture.h"
#else
#include "../texture/ssTgaPicture.h"
#endif


namespace StarSeeker
{

ssResManager::ssResManager()
{
}

ssResManager::~ssResManager()
{
	Clear();
}

ssError ssResManager::LoadFile(const char* uri)
{
	if (uri)
	{
		char hash[34] = {};
		GetMd5(uri, ::strlen(uri), hash);
		if (FindRes(hash))
		{
			return SS_LOADRES_EXISTS;
		}
		ssBinaryFile* bf = new ssBinaryFile(uri);
		std::string path = SS_GET_RES_PATH(uri);
		if (bf->LoadFile(path.c_str()))
		{
			m_mapRes.Insert(bf, hash, 32);
			return SS_OK;
		}
		else
		{
			delete bf;
		}
	}
	return SS_LOADRES_ERROR;
}

ssError ssResManager::LoadMesh(const char* uri)
{
	if (uri)
	{
		char hash[34] = {};
		GetMd5(uri, ::strlen(uri), hash);
		if (FindRes(hash))
		{
			return SS_LOADRES_EXISTS;
		}
		ssMesh* pm = new ssMesh(uri);
		std::string path = SS_GET_RES_PATH(uri);
		if (pm->LoadFromFile(path.c_str()))
		{
			m_mapRes.Insert(pm, hash, 32);
			return SS_OK;
		}
		delete pm;
	}
	return SS_LOADRES_ERROR;
}

ssError ssResManager::CreateMesh(ssMesh* mesh)
{
	if (mesh)
	{
		if (FindRes(mesh->Hash()))
		{
			return SS_LOADRES_EXISTS;
		}
		m_mapRes.Insert(mesh, mesh->Hash(), 32);
		return SS_OK;
	}
	return SS_LOADRES_ERROR;
}

ssError ssResManager::LoadPicture(const char* uri)
{
	if (uri)
	{
		char hash[34] = {};
		GetMd5(uri, ::strlen(uri), hash);
		if (FindRes(hash))
		{
			return SS_LOADRES_EXISTS;
		}
		ssTextureSpirit2d* pt = new ssTextureSpirit2d(uri);
		std::string path = SS_GET_RES_PATH(uri);
		if (pt->LoadFromFile(path.c_str()))
		{
			m_mapRes.Insert(pt, hash, 32);
			return SS_OK;
		}
		delete pt;
	}
	return SS_LOADRES_ERROR;
}

ssError ssResManager::CreateTexture2d(const char* uri, i32 width, i32 height)
{
	if (uri)
	{
		char hash[34] = {};
		GetMd5(uri, ::strlen(uri), hash);
		if (FindRes(hash))
		{
			return SS_LOADRES_EXISTS;
		}
		ssTextureSpirit2d* pt = new ssTextureSpirit2d(uri);
		if (pt->CreateEmpty(width, height))
		{
			m_mapRes.Insert(pt, hash, 32);
			return SS_OK;
		}
		delete pt;
	}
	return SS_LOADRES_ERROR;
}

StarSeeker::ssIRes* ssResManager::QuoteRes(const char* hash)
{
	ssAsciiDictionary<ssIRes>::Iterator itr = m_mapRes.Find(hash,32);
	if (itr.IsVaild())
	{
		itr.Data()->IncRef();
		return itr.Data();
	}
	return 0;
}

StarSeeker::ssIRes* ssResManager::QuoteResByUri(const char* uri)
{
	char hash[34] = {};
	GetMd5(uri, ::strlen(uri), hash);
	return QuoteRes(hash);
}

bool ssResManager::RecoverRes(const char* hash)
{
	ssAsciiDictionary<ssIRes>::Iterator itr = m_mapRes.Find(hash, 32);
	if (itr.IsVaild())
	{
		itr.Data()->DecRef();
		if (!itr.Data()->GetWithoutRef() && itr.Data()->Ref()<=0)
		{
			m_mapRes.Erase(itr);
		}
		return true;
	}
	return false;
}

bool ssResManager::RecoverResByUri(const char* uri)
{
	char hash[34] = {};
	GetMd5(uri, ::strlen(uri), hash);
	return RecoverRes(hash);
}

bool ssResManager::RecoverRes(ssIRes* res)
{
	return RecoverRes(res->Hash());
}

void ssResManager::Clear()
{
	m_mapRes.Clear();
}

const StarSeeker::ssIRes* ssResManager::FindRes(const char* hash)
{
	ssAsciiDictionary<ssIRes>::Iterator itr = m_mapRes.Find(hash, 32);
	if (itr.IsVaild())
	{
		return itr.Data();
	}
	return 0;
}

const StarSeeker::ssIRes* ssResManager::FindResByUri(const char* uri)
{
	char hash[34] = {};
	GetMd5(uri, ::strlen(uri), hash);
	return FindRes(hash);
}

void ssResManager::ReleaseZero()
{
	ssList<ssAsciiDictionary<ssIRes>::Iterator> del;
	ssAsciiDictionary<ssIRes>::Iterator itr = m_mapRes.Begin();
	while (itr.IsVaild())
	{
		if (!itr.Data()->GetWithoutRef() && itr.Data()->Ref() <= 0)
		{
			//delete itr.Data();
			del.PushBack(itr);
		}
		++itr;
	}
	ssList<ssAsciiDictionary<ssIRes>::Iterator>::Iterator idel = del.Begin();
	while (idel.IsVaild())
	{
		m_mapRes.Erase(*idel);
		++idel;
	}
}

void ssResManager::CreateDefaultMesh()
{
	char hash[34] = {};
	{
		ssfloat v[4 * 3] = { -0.5f,0.0f,0.5f, -0.5f,0.0f,-0.5f,0.5f,0.0f,-0.5f,0.5f,0.0f,0.5f };
		u8 f[2 * 3] = { 0,1,2, 0,2,3 };
		ssfloat t[4 * 2] = { 0.0f,1.0f, 0.0f,0.0f, 1.0f,0.0f, 1.0f,1.0f };
		ssMesh* pPanel = new ssMesh("panel");
		pPanel->CreateVertex(v, 12);
		pPanel->CreateIndex(SS_INDEX_8, f, 6);
		pPanel->CreateTexture2d(t, 8);
		pPanel->WithoutRef(true);
		m_mapRes.Insert(pPanel, pPanel->Hash(), 32);
	}
	{
		ssfloat v[4 * 3] = { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f };
		u8 f[2 * 3] = { 0,1,0,2,0,3 };
		ssfloat c[4 * 4] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f };
		ssMesh* pAxes = new ssMesh("axes");
		pAxes->CreateVertex(v, 12);
		pAxes->CreateIndex(SS_INDEX_8, f, 6);
		pAxes->CreateColor(c, 16);
		pAxes->WithoutRef(true);
		m_mapRes.Insert(pAxes, pAxes->Hash(), 32);
	}
	{
		ssfloat v[4 * 3] = { -0.5f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.5f, 0.5f, 0.0f };
		u8 f[2 * 3] = { 0, 1, 2, 0, 2, 3 };
		ssfloat t[4 * 2] = { 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
		ssfloat n[4 * 3] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f };
		ssfloat tg[4 * 3] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
		ssMesh* pQuad = new ssMesh("quad");
		pQuad->CreateVertex(v, 12);
		pQuad->CreateIndex(SS_INDEX_8, f, 6);
		pQuad->CreateTexture2d(t, 8);
		pQuad->CreateNormal(n, 12);
		pQuad->CreateTangent(tg, 12);
		pQuad->WithoutRef(true);
		m_mapRes.Insert(pQuad, pQuad->Hash(), 32);
	}
	{
		f32 v[6 * 3] = { 0.0f,0.0f,0.5f, -0.0f,0.5f,-0.0f, -0.5f,-0.0f,-0.0f, 0.0f,-0.5f,-0.0f, 0.5f,0.0f,-0.0f, 0.0f,0.0f,-0.5f };
		u8 f[8 * 3] = { 0,1,2,0,2,3,0,3,4,0,4,1,5,2,1,5,3,2,5,4,3,5,1,4 };
		f32 c[6 * 4] = { 0.0,0.0,1.0,1.0, 0.0,1.0,0.0,1.0, 1.0,1.0,1.0,1.0, 1.0,1.0,1.0,1.0, 1.0,0.0,0.0,1.0, 1.0,1.0,1.0,1.0 };
		ssMesh* pDiamond = new ssMesh("diamond");
		pDiamond->CreateVertex(v, 18);
		pDiamond->CreateIndex(SS_INDEX_8, f, 24);
		pDiamond->CreateColor(c, 24);
		pDiamond->WithoutRef(true);
		m_mapRes.Insert(pDiamond, pDiamond->Hash(), 32);
	}
}

}
